package domain;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import aima.core.util.datastructure.XYLocation;

public class PacmanBoard {
	
	// ROW NUMBER == Y COORDINATE
	// COL NUMBER == X COORDINATE
	
	private char[][] map;
	private List<XYLocation> crumbs;
	private XYLocation pacmanLocation;
	
	public PacmanBoard(char[][] map) {
		this.map = map;
		initLocations();
		eatCrumbs();
	}
	
	public PacmanBoard(char[][] map, List<XYLocation> crumbs, XYLocation pacmanLocation) {
		this.map = map;
		this.crumbs = crumbs;
		this.pacmanLocation = pacmanLocation;
		map[pacmanLocation.getYCoOrdinate()][pacmanLocation.getXCoOrdinate()] = 'P';
		eatCrumbs();
	}
	
	private void initLocations() 
	{
		crumbs = new ArrayList<>();
		for(int row = 0; row < map.length; row++) 
		{
			for(int col = 0; col < map[row].length; col++) 
			{
				if(map[row][col] == 'P')
					pacmanLocation = new XYLocation(col, row);
				if(map[row][col] == '.')
					crumbs.add(new XYLocation(col, row));
			}
		}
	}
	
	private void eatCrumbs() {
		Iterator<XYLocation> it = crumbs.iterator();
		while(it.hasNext()) {
			XYLocation crumb = it.next();
			if(crumb.equals(pacmanLocation)) {
				it.remove();
				map[crumb.getYCoOrdinate()][crumb.getXCoOrdinate()] = ' ';
			}
		}
	}
	
	public char[][] getMap() 
	{
		char[][] mapClone = new char[map.length][map[0].length];
		
		for (int row = 0; row < map.length; row++)
		{
			for (int col = 0; col < map[0].length; col++) 
			{
				mapClone[row][col] = map[row][col];
			}
		}
		return mapClone;
	}
	
	public List<XYLocation> getCrumbs() {
		List<XYLocation> crumbsClone = new ArrayList<>();
		for(XYLocation crumb: crumbs) {
			crumbsClone.add(new XYLocation(crumb.getXCoOrdinate(), crumb.getYCoOrdinate()));
		}
		return crumbsClone;
	}
	
	public XYLocation getFinishLocation() {
		return crumbs.size() > 0 ? crumbs.get(0) : null;
	}
	
	public int getNumberOfRemainingCrumbs() {
		return crumbs.size();
	}
	
	public XYLocation getPacmanLocation() {
		return pacmanLocation;
	}
	
	public boolean canMoveUp(){
		if( (map[pacmanLocation.getYCoOrdinate()-1][pacmanLocation.getXCoOrdinate()] != '%')  && (map[pacmanLocation.getYCoOrdinate()-1][pacmanLocation.getXCoOrdinate()] != 'P') )
			return true;
		return false;
	}
	
	public boolean canMoveDown() {
		if( (map[pacmanLocation.getYCoOrdinate()+1][pacmanLocation.getXCoOrdinate()] != '%')  && (map[pacmanLocation.getYCoOrdinate()+1][pacmanLocation.getXCoOrdinate()] != 'P') )
			return true;
		return false;
	}
	
	public boolean canMoveLeft() {
		if( (map[pacmanLocation.getYCoOrdinate()][pacmanLocation.getXCoOrdinate()-1] != '%')  && (map[pacmanLocation.getYCoOrdinate()][pacmanLocation.getXCoOrdinate()-1] != 'P') )
			return true;
		return false;
	}
	
	public boolean canMoveRight() {
		if( (map[pacmanLocation.getYCoOrdinate()][pacmanLocation.getXCoOrdinate()+1] != '%')  && (map[pacmanLocation.getYCoOrdinate()][pacmanLocation.getXCoOrdinate()+1] != 'P') )
			return true;
		return false;
	}
	
	public void printBoard() {
		char[][] mapToPrint = map.clone();
		for(int row = 0; row < mapToPrint.length; row++) {
			for(int col = 0; col < mapToPrint[row].length; col++) {
				System.out.print(mapToPrint[row][col]);
			}
			System.out.print("\n");
		}
	}

	public XYLocation getClosestCrumbTo(XYLocation actor) {

		if (crumbs.size() > 0) {
			XYLocation closestCrumb = crumbs.get(0);

			for (XYLocation crumb : crumbs) {
				double distanceToCurrentClosestCrumb = Math.sqrt(Math.pow(
						actor.getXCoOrdinate() - closestCrumb.getXCoOrdinate(),
						2)
						+ Math.pow(
								actor.getYCoOrdinate()
										- closestCrumb.getYCoOrdinate(), 2));
				double distanceToCrumb = Math
						.sqrt(Math.pow(actor.getXCoOrdinate() - crumb.getXCoOrdinate(),
								2)
								+ Math.pow(
										actor.getYCoOrdinate()
												- crumb.getYCoOrdinate(), 2));
				if (distanceToCrumb < distanceToCurrentClosestCrumb) {
					closestCrumb = crumb;
				}
			}
			return closestCrumb;
		}
		return null;

	}
}
